package com.kaifamiao.wendao.controller;

import com.kaifamiao.wendao.entity.Customer;
import com.kaifamiao.wendao.entity.Topic;
import com.kaifamiao.wendao.service.TopicService;
import com.kaifamiao.wendao.utils.Constants;
import com.kaifamiao.wendao.utils.Pagination;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.tinylog.Logger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@WebServlet("/topic/*")
public class TopicServlet extends HttpServlet {

    private TopicService topicService;

    @Override
    public void init() throws ServletException {
        topicService = new TopicService();
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String method = request.getMethod();
        String uri = request.getRequestURI();
        // GET "/topic/list"
        if( "GET".equals(method) && uri.endsWith( "/list" )){
            this.list(request,response);
        }
        // GET "/topic/publish"
        if( "GET".equals(method) && uri.endsWith( "/publish" )){
            this.publishPage(request,response);
        }
        // POST "/topic/publish"
        if( "POST".equals(method) && uri.endsWith( "/publish" )){
            this.publishAction(request,response);
        }
        // GET "/topic/detail"
        if( "GET".equals(method) && uri.endsWith( "/detail" )){
            this.detail(request,response);
        }
        // GET "/topic/mine"
        if( "GET".equals(method) && uri.endsWith( "/mine" )){
            this.mine(request,response);
        }
        // GET "/topic/{TOPIC_ID}/explain"
        if( "GET".equals(method) && uri.endsWith( "/explain" )){
            this.explainPage(request,response);
        }
    }

    private Map<String,Integer> pagingConditions(HttpServletRequest request){
        HttpSession session = request.getSession();
        // 尝试从会话中获取pageSize属性值并以此为每页所显示的行数值
        Integer pageSize = (Integer)session.getAttribute("pageSize");
        // 若会话中没有pageSize属性则采用默认值
        pageSize = pageSize == null ? Constants.DEFAULT_PAGE_SIZE : pageSize ;
        // 尝试从请求参数中获取 size 参数值
        final String size = request.getParameter("size");
        // 若请求参数中的 size 是存在的
        if( !StringUtils.isEmpty(size) && !StringUtils.isBlank(size) ){
            // 将请求参数中的 size 参数值转化为整数
            pageSize = Integer.valueOf(size);
            // 将 size 参数值设置到 会话的属性中
            session.setAttribute("pageSize", pageSize);
        }
        final String current = request.getParameter("current");
        int currentPage = StringUtils.isEmpty(current) ? Constants.DEFAULT_CURRENT_PAGE : Integer.parseInt(current);
        return Map.of("pageSize", pageSize, "currentPage", currentPage);
    }

    // GET "/topic/list"
    protected void list(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String uri = request.getRequestURI();
        request.setAttribute("path", uri );
        Map<String,Integer> map = pagingConditions(request);
        // 根据分页条件查询数据
        Pagination<Topic> p = topicService.load(map.get("currentPage"), map.get("pageSize"));
        // 将查询到的话题列表设置到请求属性中(将来可以在JSP中通过EL表达式来获取)
        request.setAttribute("pagination", p);
        String path = "/WEB-INF/pages/topic/list.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        // 将请求转发到指定资源
        dispatcher.forward(request, response);
    }

    // GET "/topic/publish"
    protected void publishPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String path = "/WEB-INF/pages/topic/publish.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    private boolean validate(HttpServletRequest request) throws ServletException, IOException {
        // 检查话题的标题是否为空
        // 检查话题的内容是否为空
        return true;
    }

    // POST "/topic/publish"
    protected void publishAction(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if(this.validate(request)) {
            HttpSession session = request.getSession();
            Topic t = new Topic();
            try {
                // 将请求对象中的参数值填充到Topic实例中
                BeanUtils.populate(t,request.getParameterMap());
            } catch (Exception e) {
                session.setAttribute("message", "服务器内部错误: 数据收集失败");
                Logger.error(e);
            }

            String addr = request.getRemoteAddr();
            Logger.trace("address: {}", addr);
            // 设置发布者的IP地址
            t.setPublishAddress(addr);

            Customer logined = (Customer)session.getAttribute(Constants.CUSTOMER_LOGINED);
            // 以当前登录用户为话题的发布者
            t.setAuthor(logined);

            try {
                if (topicService.save(t)) {
                    response.sendRedirect(request.getContextPath() + "/topic/list");
                    return;
                }
                session.setAttribute("message", "话题发布失败");
                session.setAttribute("title", t.getTitle());
                session.setAttribute("content", t.getContent());
            } catch (Exception e){
                Logger.error(e);
                session.setAttribute("message", "话题发布失败");
                session.setAttribute("title", t.getTitle());
                session.setAttribute("content", t.getContent());
            }
        }
        response.sendRedirect(request.getContextPath()+"/topic/publish");
    }

    // GET "/topic/detail"
    protected void detail(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String sid = request.getParameter("id");
        if(StringUtils.isEmpty(sid) || StringUtils.isBlank(sid)){
            response.sendRedirect(request.getContextPath()+"/topic/list");
            return;
        }
        Long id = Long.valueOf(sid);
        Topic t = topicService.load(id);
        request.setAttribute("topic", t );
        String path = "/WEB-INF/pages/topic/detail.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    // GET "/topic/mine"
    protected void mine(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String uri = request.getRequestURI();
        request.setAttribute("path", uri );
        Map<String,Integer> map = pagingConditions(request);
        Integer current = map.get("currentPage");
        Integer size = map.get("pageSize");
        HttpSession session = request.getSession();
        Customer me = (Customer)session.getAttribute(Constants.CUSTOMER_LOGINED);
        // 查询当前用户的所有话题
        Pagination<Topic> p = topicService.loadByCustomer(me, current,size);
        request.setAttribute("pagination", p);
        String path = "/WEB-INF/pages/topic/list.jsp";
        RequestDispatcher dispatcher = request.getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    // GET "/topic/{TOPIC_ID}/explain"
    protected void explainPage(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        final String uri = request.getRequestURI();
        Pattern p = Pattern.compile("\\d{19}");
        Matcher m = p.matcher(uri);
        if(m.find()) {
            String sid = m.group();
            Long id = Long.valueOf(sid);
            Topic t = topicService.load(id);
            request.setAttribute("topic", t );
            String path = "/WEB-INF/pages/topic/explain.jsp";
            RequestDispatcher dispatcher = request.getRequestDispatcher(path);
            dispatcher.forward(request, response);
            return;
        }
        response.sendRedirect(request.getContextPath()+"/topic/list");
    }

}
